import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import { getToken, removetoken, saveToken } from './token.js'
import { Toast } from 'vant'
import router from '@/router/index.js'
import JSONbig from 'json-bigint'

Vue.use(VueAxios, axios)
// 1.创建axios的instance实例（创建axios副本与axios无异，知识多了基地址）
// 为什么建立axios副本？
// （1）
// （2）有的项目不止一个基地址，封装起来，独立使用
const instance = axios.create({
  // 接口基地址
  baseURL: 'http://toutiao-app.itheima.net',
  // 网络请求延迟时间
  timeout: 10000,

  //使用自定义方式来解决默认的json解析
  // `transformResponse` 在传递给 then/catch 前，允许修改响应数据
  transformResponse: [
    // 此处的data是服务器响应回来的原始数据！
    function (data) {
      try {
        return JSONbig.parse(data)
      } catch (err) {
        // 取消关注接口，服务器没有返回数据。所以解析不出来，报错(直接返回服务器的原始数据)
        //
        return data
      }
      // 对 data 进行任意转换处理
      return data
    }
  ]
  // 因为此处的请求头格式是json格式，所以不用设置请求头格式！
  //   headers: { 'X-Custom-Header': 'foobar' }
})

// // 一、使用axios请求拦截自动添加token
// // 原因：每次发送请求都要设置请求头。在请求过程中拦截请求，自动添加token。以后每一次发送请求就不用手动添加token。
// // 添加请求拦截器
// instance.interceptors.request.use(
//   function (config) {
//     // 在发送请求之前做些什么
//     if (getToken()) {
//       //如果有token的话，才需要在请求头自动添加token！
//       config.headers = { Authorization: `Bearer ${getToken().token}` }
//     }
//     return config
//   },
//   function (error) {
//     // 对请求错误做些什么
//     return Promise.reject(error)
//   }
// )

// // 二、使用axios相应拦截实现token刷新
// // （上面代码，instance会自动在请求拦截中添加token。但是执行到这里说明token已经过期了），所以刷新token接口不能用instance来发送，而应该使用axios。
// axios.interceptors.response.use(
//   function (response) {
//     // 对响应数据做点什么
//     return response
//   },
//   async function (error) {
//     // 对响应错误做点什么
//     // 如果是401错误
//     if (error.response.status == 401) {
//       // token过期控制台爆红，手动清除控制台打印
//       // setTimeout(() => {
//       //   console.clear()
//       // }, 2000)

//       // （1）如果是token过期
//       if (getToken()) {
//         // （1.1)刷新token
//         try {
//           let res = await axios({
//             url: 'http://toutiao-app.itheima.net/v1_0/authorizations',
//             method: 'put',
//             headers: { Authorization: `Bearer ${getToken().refresh_token}` }
//           })
//           console.log(res)
//           saveToken({
//             token: res.data.data.token,
//             refresh_token: getToken().refresh_token
//           })
//           // let newToken = getToken()
//           // newToken.token = res.data.data.token
//           // saveToken(newToken)

//           // 更新token成功之后，重新发送原本的接口请求。返回当前配置信息
//           return instance(error.config)
//         } catch (err) {
//           // （1.2）刷新token失败，说明refresh_token也过期了。重新设置token
//           Toast.fail('请先登录！')
//           removetoken()
//           router.push({ path: '/login' })
//         }
//       } else {
//         // （2）如果是没登录
//         Toast.fail('请先登录！')
//         router.push({ path: '/login' })
//       }
//     } else {
//       // 如果不是401错误，说明是其它问题，不做处理
//     }
//     return Promise.reject(error)
//   }
// )

// 一、添加请求拦截器(每次接口请求之前拦截请求，自动添加请求头。以后每一次请求就不用再写请求头了)
instance.interceptors.request.use(
  function (config) {
    // 在发送请求之前做些什么
    if (getToken()) {
      config.headers = { Authorization: `Bearer ${getToken().token}` }
    }
    // config是请求对象，相当于instance里面的请求对象，url/method/参数
    return config
  },
  function (error) {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)

// 二、刷新token，不要老是出现401错误（在响应401错误之前拦截下来）
// 添加响应拦截器
instance.interceptors.response.use(
  function (response) {
    // 对响应数据做点什么
    return response
  },
  async function (error) {
    // 对响应错误做点什么
    if (error.response.status == 401) {
      if (getToken()) {
        try {
          let res = await axios({
            url: 'http://toutiao-app.itheima.net/v1_0/authorizations',
            method: 'put',
            headers: { Authorization: `Bearer ${getToken().refresh_token}` }
          })
          console.log(res)
          saveToken({
            token: res.data.data.token,
            refresh_token: getToken().refresh_token
          })
          return instance(error.config)
        } catch (err) {
          Toast.fail('请重新登录！')
          removetoken()
          router.push({ path: '/login' })
        }
      } else {
        Toast.fail('请先登录！')
        router.push({ path: '/login' })
      }
    }
    return Promise.reject(error)
  }
)

// 2.输出
export default instance
